package com.csun.cmny.provider.controller;

import com.csun.cmny.base.dto.LoginAuthDto;
import com.csun.cmny.base.enums.ErrorCodeEnum;
import com.csun.cmny.core.annotation.ValidateAnnotation;
import com.csun.cmny.core.support.BaseController;
import com.csun.cmny.provider.dao.OmcNursingRoomBindMapper;
import com.csun.cmny.provider.dto.Group;
import com.csun.cmny.provider.dto.OmcOldLeaveDto;
import com.csun.cmny.provider.dto.OmcOldLeaveQueryDto;
import com.csun.cmny.provider.exceptions.OmcBizException;
import com.csun.cmny.provider.model.domain.OmcNursingUserBind;
import com.csun.cmny.provider.model.domain.OmcOldManSupplement;
import com.csun.cmny.provider.model.dto.old_leave.OldLeaveDaysDto;
import com.csun.cmny.provider.model.dto.old_leave.OldLeaveOldmanQueryDto;
import com.csun.cmny.provider.model.vo.nursing.NursingGroupOldmanVo;
import com.csun.cmny.provider.model.vo.old_leave.OldLeaveDaysVo;
import com.csun.cmny.provider.model.vo.old_leave.OldLeaveOldmanVo;
import com.csun.cmny.provider.pojo.NursingGroup;
import com.csun.cmny.provider.pojo.OmcOldLeave;
import com.csun.cmny.provider.resolver.CmnyMessageSource;
import com.csun.cmny.provider.service.*;
import com.csun.cmny.provider.validator.OmcOldLeaveValidator;
import com.csun.cmny.provider.vo.NursingGroupVo;
import com.csun.cmny.provider.vo.OldLeaveVo;
import com.csun.cmny.provider.vo.OldUnLeaveVo;
import com.csun.cmny.provider.vo.OmcAdjustRefundData;
import com.csun.cmny.util.DateUtil;
import com.csun.cmny.util.PublicUtil;
import com.csun.cmny.util.wrapper.WrapMapper;
import com.csun.cmny.util.wrapper.Wrapper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.http.MediaType;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Pattern;

/**
 * @author chenzheng
 * @description:老人请假模块控制器
 * @date 2019/7/22 14:16
 */
@RestController
@RequestMapping(value = "/oldLeave", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public class OmcOldLeaveController extends BaseController {

    @Resource
    private CmnyMessageSource cmnyMessageSource;
    @Resource
    private OmcOldLeaveService omcOldLeaveService;
    @Resource
    private OmcGroupService omcGroupService;
    @Resource
    private OmcOldmanStatusService omcOldmanStatusService;
    @Resource
    private OmcNursingRoomBindMapper omcNursingRoomBindMapper;
    @Resource
    private OmcReturnFeeConfigService omcReturnFeeConfigService;
    @Resource
    private OmcNursingUserBindService omcNursingUserBindService;
    @Resource
    private OmcOldManSupplementService omcOldManSupplementService;


    /**
     * 提交请假
     *
     * 如果第一次请假，请假日期只能在今天之后
     * 如果之前请过假，请假日期只能在上一次回院之后（适用第一条）
     *
     */
    @ValidateAnnotation
    @RequestMapping(value = "/add", method = RequestMethod.POST)
    public Wrapper oldLeaveAdd(@RequestBody @Validated(value = {OmcOldLeaveValidator.class}) OmcOldLeaveDto oldLeaveDto, BindingResult br) {

        Long oldmanId = oldLeaveDto.getOldManId();
        Long groupId = getLoginAuthDto().getGroupId();
        oldLeaveDto.setGroupId(groupId);
        // 初步判断请假时间和回院时间及请假天数
        if (oldLeaveDto.getLeaveDate().compareTo(oldLeaveDto.getReturnDate()) > 0) {
            return WrapMapper.wrap(Wrapper.ILLEGAL_ARGUMENT_CODE_, cmnyMessageSource.getMessage("OldLeaveController.add.paramerror", null), null);
        }else {
            try {
                if (oldLeaveDto.getLeaveDate().compareTo(DateUtil.getDateStr(new Date())) < 0){
                    /**
                     * @author  chisj
                     * @date    2021-08-18 11:44
                     * @desc    暂时不校验请假开始时间
                     */
                    // return WrapMapper.wrap(Wrapper.ILLEGAL_ARGUMENT_CODE_, cmnyMessageSource.getMessage("OldLeaveController.add.date.is.error", null), null);
                } else {
                    int days = (int) DateUtil.diffDays(oldLeaveDto.getLeaveDate(), oldLeaveDto.getReturnDate());

            /**
             * @dese    实际请假天数为0天时，是否算作请1天假根据配置
             *          （cn_omc_return_fee_config中的is_zero）判断
             *          0 - 实际请假天数为0
             *          1 - 实际请假天数为1
             */
            OmcOldManSupplement omcOldManSupplement = new OmcOldManSupplement();
            omcOldManSupplement.setOldManId(oldmanId);
            omcOldManSupplement = omcOldManSupplementService.selectOne(omcOldManSupplement);
            String inDate = omcOldManSupplement.getInDate();

            // 查询退费周期数
            OldLeaveDaysDto oldLeaveDaysDto = new OldLeaveDaysDto();

            oldLeaveDaysDto.setStartDate(com.csun.cmny.util.DateUtil.stringToDate(oldLeaveDto.getLeaveDate()));
            oldLeaveDaysDto.setEndDate(com.csun.cmny.util.DateUtil.stringToDate(oldLeaveDto.getReturnDate()));
            oldLeaveDaysDto.setGroupId(groupId);
            oldLeaveDaysDto.setInDate(com.csun.cmny.util.DateUtil.stringToDate(inDate));

            // 查询老人请假退费周期数
            OldLeaveDaysVo oldLeaveDaysVo = omcReturnFeeConfigService.queryOldLeaveDaysVo(oldLeaveDaysDto);
            oldLeaveDto.setRefundDays(oldLeaveDaysVo.getReturnDays());
            oldLeaveDto.setRealRefundDays(oldLeaveDaysVo.getRealLeaveDays());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        /**
         * @desc    老人请假时间不能在已经请假-销假的时间内
         * @date    2019-10-08
         * @author  chisj
         */
        int count = omcOldLeaveService.queryCountByLeaveDate(oldLeaveDto.getOldManId(), oldLeaveDto.getLeaveDate());
        if (count > 0) {
            throw new OmcBizException(ErrorCodeEnum.OMC10031205);
        }



        /**
         * 查询班组
         */
        NursingGroupOldmanVo nursingGroupOldmanVo = omcNursingRoomBindMapper
                .queryNursingGroupOldmanByOldmanId(oldLeaveDto.getOldManId().intValue());
        if (PublicUtil.isEmpty(nursingGroupOldmanVo)) {
            throw new OmcBizException(ErrorCodeEnum.OMC10031206);
        }

        /**
         * @author  chisj
         * @date    2021-08-18 16:23
         * @desc    修复班长在多个班组无法请假的问题
         */
//        OmcNursingUserBind nursingUserBind = new OmcNursingUserBind();
//        nursingUserBind.setUserId(getLoginAuthDto().getUserId());
//        nursingUserBind = omcNursingUserBindService.selectOne(nursingUserBind);
//        if (nursingUserBind == null || nursingUserBind.getNursingGroupId() == null) {
//            throw new OmcBizException(ErrorCodeEnum.OMC10031206);
//        }

      /*  if (!nursingUserBind.getNursingGroupId().equals(nursingGroupOldmanVo.getNursingGroupId())) {
            throw new OmcBizException(ErrorCodeEnum.OMC10031206);
        }*/
        oldLeaveDto.setNursingGroupId(nursingGroupOldmanVo.getNursingGroupId());



        int n = saveOmcOldLeave(oldLeaveDto);
        if (n <= 0) {
            return WrapMapper.wrap(Wrapper.ERROR_CODE, cmnyMessageSource.getMessage("OldLeaveController.add.qingjiafail", null), n);
        }

        return WrapMapper.wrap(Wrapper.SUCCESS_CODE, cmnyMessageSource.getMessage("OldLeaveController.add.qingjiachenggong", null), n);
    }


    /**
     * 老人请假删除
     */
    @RequestMapping(value = "/del", method = RequestMethod.POST)
    public Wrapper oldLeaveDel(Integer id) {
        //需删除的记录ID不能为空
        if (id == null || 0 == id) {
            return WrapMapper.wrap(Wrapper.ILLEGAL_ARGUMENT_CODE_, cmnyMessageSource.getMessage("OldLeaveController.del.delparamerror", null), null);
        }
        int n = omcOldLeaveService.deleteByKey(id);
        if (n <= 0) {
            return WrapMapper.wrap(Wrapper.ERROR_CODE, cmnyMessageSource.getMessage("OldLeaveController.del.fail", null), n);
        }

        return WrapMapper.wrap(Wrapper.SUCCESS_CODE, cmnyMessageSource.getMessage("OldLeaveController.del.success", null), n);
    }


    /**
     * 老人销假
     *
     * 回院日期只能在今天及之前（不能比请假日期早）
     *
     */
    @RequestMapping(value = "/sell", method = RequestMethod.POST)
    public Wrapper oldLeaveSell(@RequestBody OmcOldLeaveDto oldLeaveDto) {
        oldLeaveDto.setGroupId(getLoginAuthDto().getGroupId());
        String pattern = "^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])"
                + "|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|"
                + "[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29)$";
        //判断比传参数是否无误
        if (null == oldLeaveDto.getId() || 0 == oldLeaveDto.getId()) {
            return WrapMapper.wrap(Wrapper.ILLEGAL_ARGUMENT_CODE_, cmnyMessageSource.getMessage("EmpLeave.qingjia.id.notnull", null), null);
        }
        if (StringUtils.isNotBlank(oldLeaveDto.getRealDate()) && !Pattern.matches(pattern, oldLeaveDto.getRealDate())) {
            return WrapMapper.wrap(Wrapper.ILLEGAL_ARGUMENT_CODE_, cmnyMessageSource.getMessage("OldLeave.real.backDate.error", null), null);
        }
        //判断请假记录是否存在
        OmcOldLeave omcOldLeave = omcOldLeaveService.selectByKey(oldLeaveDto.getId());
        if (null == omcOldLeave) {
            return WrapMapper.wrap(Wrapper.ERROR_CODE, cmnyMessageSource.getMessage("OldLeaveController.sell.idnotexist", null), null);
        }
//        if(omcOldLeave.getRefundDays().intValue() != omcOldLeave.getRealRefundDays().intValue()){
//            return WrapMapper.wrap(Wrapper.ERROR_CODE, cmnyMessageSource.getMessage("OldLeaveController.old.is.not.update", null), null);
//        }
        /**
         * 判断是否进行过销假
         **/
        if (PublicUtil.isNotEmpty(omcOldLeave.getRealDate())) { // 实际回院日期不为空,说明已经回院
            return WrapMapper.wrap(Wrapper.ERROR_CODE, cmnyMessageSource.getMessage("OldLeaveController.old.is.not.update", null), null);
        }
        // 初步判断请假时间和实际回院时间及请假天数
        if (omcOldLeave.getLeaveDate().compareTo(oldLeaveDto.getRealDate()) > 0) {
            return WrapMapper.wrap(Wrapper.ILLEGAL_ARGUMENT_CODE_, cmnyMessageSource.getMessage("OldLeaveController.sell.paramerror", null), null);
        } else {
//            try {
                if(oldLeaveDto.getRealDate().compareTo(DateUtil.getDateStr(new Date())) > 0){
                    //实际回院时间不能大于今天
                    return WrapMapper.wrap(Wrapper.ILLEGAL_ARGUMENT_CODE_, cmnyMessageSource.getMessage("OldLeaveController.sell.date.is.error", null), null);
                }
//                else {
//                    int days = (int) DateUtil.diffDays(omcOldLeave.getLeaveDate(), oldLeaveDto.getRealDate());
//                    /**
//                     * @dese    实际请假天数为0天时，是否算作请1天假根据配置
//                     *          （cn_omc_return_fee_config中的is_zero）判断
//                     *          0 - 实际请假天数为0
//                     *          1 - 实际请假天数为1
//                     */
//                    OmcReturnFeeConfig omcReturnFeeConfig = omcReturnFeeConfigService
//                            .selectByGroupId(getLoginAuthDto().getGroupId());
//                    if(days == 0   // 实际请假天数为0天
//                        && PublicUtil.isNotEmpty(omcReturnFeeConfig)
//                        && omcReturnFeeConfig.getIsZero().equals(1)) {  // 配置了当请假实际天数为0天时算1天
//                        //当天请假当天回,算作一天请假
//                        days = 1;
//                    }
//                    oldLeaveDto.setRefundDays(omcOldLeaveService.getRefundDays(getLoginAuthDto().getGroupId(),days));
//                    oldLeaveDto.setRealRefundDays(oldLeaveDto.getRefundDays());
                }
//            } catch (ParseException e) {
//                e.printStackTrace();
//            }
//        }
        // omcOldLeave.setRealRefundDays(oldLeaveDto.getRealRefundDays());
        // omcOldLeave.setReturnDate(oldLeaveDto.getReturnDate());
        omcOldLeave.setRealDate(oldLeaveDto.getRealDate());
        omcOldLeave = omcOldLeaveService.calculateRefundFee(omcOldLeave, getLoginAuthDto());

        oldLeaveDto.setRefundFee(omcOldLeave.getRefundFee());
        oldLeaveDto.setReturnDegree(omcOldLeave.getReturnDegree());
        oldLeaveDto.setRealRefundDays(omcOldLeave.getRealRefundDays());
        oldLeaveDto.setRefundDays(omcOldLeave.getRefundDays());


        oldLeaveDto.setOldManId(omcOldLeave.getOldManId());

        //销假
        int n = saveOmcOldLeave(oldLeaveDto);
        if (n <= 0) {
            return WrapMapper.wrap(Wrapper.ERROR_CODE, cmnyMessageSource.getMessage("OldLeaveController.sell.fail", null), n);
        }
        // 标记老人请假结束
        omcOldmanStatusService.oldmanLeaveEnd(omcOldLeave.getOldManId().intValue());

        return WrapMapper.wrap(Wrapper.SUCCESS_CODE, cmnyMessageSource.getMessage("OldLeaveController.sell.success", null), n);
    }


    /**
     * 根据ID查询单条请假记录
     */
    @RequestMapping(value = "/showById", method = RequestMethod.POST)
    public Wrapper showById(Long id) {
        //需查询的记录ID不能为空
        if (id == null || 0 == id) {
            return WrapMapper.wrap(Wrapper.ILLEGAL_ARGUMENT_CODE_, cmnyMessageSource.getMessage("OldLeaveController.del.delparamerror", null), null);
        }
        OldLeaveVo omcOldLeaveVo = omcOldLeaveService.showById(id);
        if (null == omcOldLeaveVo) {
            return WrapMapper.wrap(Wrapper.ERROR_CODE, cmnyMessageSource.getMessage("comment.query.fail", null), omcOldLeaveVo);
        }
        return WrapMapper.wrap(Wrapper.SUCCESS_CODE, cmnyMessageSource.getMessage("comment.query.success", null), omcOldLeaveVo);
    }


    /**
     * 调房调级--查询老人上个周期账单执行时间至调房调级的时间间的未退费的请假和退费金额
     */
    @RequestMapping(value = "/showLeaveRefundFee", method = RequestMethod.POST)
    public Wrapper showLeaveRefundFee(@RequestBody OmcOldLeaveQueryDto omcOldLeaveQueryDto) {
        omcOldLeaveQueryDto.setGroupId(getLoginAuthDto().getGroupId());
        //参数校验  yyyy-MM-dd
        String pattern = "^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])"
                + "|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|"
                + "[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29)$";
        //判断比传参数是否无误
        if (null == omcOldLeaveQueryDto.getOldManId() || 0 == omcOldLeaveQueryDto.getOldManId()) {
            return WrapMapper.wrap(Wrapper.ILLEGAL_ARGUMENT_CODE_, cmnyMessageSource.getMessage("MedicationPlan.oldman.id.notnull", null), null);
        }
        if (StringUtils.isNotBlank(omcOldLeaveQueryDto.getLastDate()) && !Pattern.matches(pattern, omcOldLeaveQueryDto.getLastDate())) {
            return WrapMapper.wrap(Wrapper.ILLEGAL_ARGUMENT_CODE_, cmnyMessageSource.getMessage("OldLeave.real.backDate.error", null), null);
        }
        OmcAdjustRefundData omcAdjustRefundData = omcOldLeaveService.showLeaveRefundFee(omcOldLeaveQueryDto);
        if (omcAdjustRefundData == null) {
            omcAdjustRefundData = new OmcAdjustRefundData();
        }
        return WrapMapper.wrap(Wrapper.SUCCESS_CODE, cmnyMessageSource.getMessage("comment.query.success", null), omcAdjustRefundData);
    }


    /**
     * 根据老人ID或者老人姓名分页查询请假记录
     */
    @RequestMapping(value = "/showAll", method = RequestMethod.POST)
    public Wrapper showAll(@RequestBody OmcOldLeaveQueryDto omcOldLeaveQueryDto) {
        omcOldLeaveQueryDto.setGroupId(getLoginAuthDto().getGroupId());
        OmcNursingUserBind nursingUserBind = new OmcNursingUserBind();
        nursingUserBind.setUserId(getLoginAuthDto().getUserId());
        /**
         * @author  chisj
         * @date    2021-08-17 15:56
         * @desc    修复班长在多个班组
         */
        List<OmcNursingUserBind> nursingUserBindList = omcNursingUserBindService.select(nursingUserBind);
        if (PublicUtil.isNotEmpty(nursingUserBindList)) {
            List<Long> nursingGroupIdList = Lists.newArrayList();
            for (OmcNursingUserBind onub : nursingUserBindList) {
                nursingGroupIdList.add(onub.getNursingGroupId());
            }
            //omcOldLeaveQueryDto.setNursingGroupId(nursingUserBind.getNursingGroupId());
            omcOldLeaveQueryDto.setNursingGroupIdList(nursingGroupIdList);
        }

        List<OldLeaveVo> list = omcOldLeaveService.showAll(omcOldLeaveQueryDto);
        PageInfo<OldLeaveVo> pageInfo = new PageInfo<>(list);
        return WrapMapper.wrap(Wrapper.SUCCESS_CODE, cmnyMessageSource.getMessage("comment.query.success", null), pageInfo);
    }


    /**
     * 查询班组可以请假的老人列表
     */
    @PostMapping(value = "/queryOldmanList")
    public Wrapper queryOldmanList(String oldmanName) {

        OldLeaveOldmanQueryDto oldLeaveOldmanQueryDto = new OldLeaveOldmanQueryDto();
        oldLeaveOldmanQueryDto.setOldmanName(oldmanName);

        /**
         * @author  chisj
         * @date    2021-08-17 16:02
         * @desc    修复班长在多个班组的问题
         */
        // 获取用户是否为班长
        NursingGroup nursingGroup = new NursingGroup();
        nursingGroup.setUserId(getLoginAuthDto().getUserId());
        List<NursingGroup> nursingGroupList = omcGroupService.select(nursingGroup);
        if (PublicUtil.isEmpty(nursingGroup)) {
            throw new OmcBizException(ErrorCodeEnum.OMC10038001);
        }
        List<Long> nursingGroupIdList = Lists.newArrayList();
        for (NursingGroup ng : nursingGroupList) {
            nursingGroupIdList.add(ng.getId());
        }
        oldLeaveOldmanQueryDto.setNursingGroupIdList(nursingGroupIdList);
        oldLeaveOldmanQueryDto.setGroupId(getLoginAuthDto().getGroupId());

        // 根据班组查询看护的房间
        List<Integer> roomIdList = omcNursingRoomBindMapper
                .queryRoomIdListByNursingGroupIdList(nursingGroupIdList);
        if (PublicUtil.isEmpty(roomIdList)) {
            throw new OmcBizException(ErrorCodeEnum.OMC10038011);
        }
        oldLeaveOldmanQueryDto.setRoomIdList(roomIdList);

        List<OldLeaveOldmanVo> oldLeaveOldmanVoList = omcOldLeaveService.queryOldmanList(oldLeaveOldmanQueryDto);

        return WrapMapper.ok(oldLeaveOldmanVoList);
    }

    /**
     * 查询用户班组老人信息
     */
    @RequestMapping(value = "/showInfo", method = RequestMethod.POST)
    public Wrapper showInfo(String name) {
        LoginAuthDto loginAuthDto = getLoginAuthDto();
        //判断登录用户是否是班长
        Group group = new Group();
        group.setUserId(loginAuthDto.getUserId());
        group.setGroupId(loginAuthDto.getGroupId());
        List<NursingGroupVo> nursingGroupList = omcGroupService.selectListByName(group);
        if (null == nursingGroupList || nursingGroupList.size() <= 0) {
            return WrapMapper.wrap(Wrapper.ERROR_CODE, cmnyMessageSource.getMessage("ReviseController.showInfo.notbelong.banzhang", null), null);
        }
        NursingGroupVo nursingGroup = nursingGroupList.get(0);
        //组建查询条件,查询班组老人信息
        OmcOldLeaveQueryDto omcOldLeaveQueryDto = new OmcOldLeaveQueryDto();
        omcOldLeaveQueryDto.setOldName(name);
        omcOldLeaveQueryDto.setGroupId(nursingGroup.getGroupId());
        omcOldLeaveQueryDto.setNursingGroupId(nursingGroup.getId().longValue());
        List<OldUnLeaveVo> list = omcOldLeaveService.selectOldManByName(omcOldLeaveQueryDto);
        List<OldUnLeaveVo> resultList = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            OldUnLeaveVo oldUnLeaveVo = list.get(i);
            OmcOldLeave omcOldLeave = new OmcOldLeave();
            omcOldLeave.setOldManId(oldUnLeaveVo.getOldManId());
            if (omcOldLeaveService.confirmLeave(omcOldLeave) <= 0) { // 判断是否需正处于请假申请中.
                resultList.add(oldUnLeaveVo);
            }
        }
        if (resultList.size() <= 0) {
            return WrapMapper.wrap(Wrapper.ERROR_CODE, cmnyMessageSource.getMessage("comment.query.fail", null), resultList);
        }
        return WrapMapper.wrap(Wrapper.SUCCESS_CODE, cmnyMessageSource.getMessage("comment.query.success", null), resultList);
    }


    /**
     * 保存或者更新老人请假
     *
     * @param: [uacPlanDto]
     * @return: java.lang.Integer
     */
    private Integer saveOmcOldLeave(OmcOldLeaveDto omcMonitorLogDto) {
        OmcOldLeave omcOldLeave = new OmcOldLeave();
        BeanUtils.copyProperties(omcMonitorLogDto, omcOldLeave);
        return omcOldLeaveService.saveOmcOldLeave(omcOldLeave, getLoginAuthDto());
    }

    /**
     * 查询今天请假老人的请假详情
     */
    @RequestMapping(value = "/selectLeaveOldman", method = RequestMethod.POST)
    public Wrapper selectLeaveOldMan(Long groupId) {
        groupId = getLoginAuthDto().getGroupId();
        List<OldLeaveOldmanVo> list =  omcOldLeaveService.selectLeaveOldMan(groupId);
        return WrapMapper.wrap(Wrapper.SUCCESS_CODE, cmnyMessageSource.getMessage("comment.query.success", null), list);
    }

}
